﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Permissions;
using System.Runtime.InteropServices;

namespace InstallManager.Msi
{
    [SecurityPermission(SecurityAction.Demand, UnmanagedCode = true)]
    internal sealed class MsiInterop
    {
        public const int MaxFeatureChars = 38;

        public const uint MessageTypeMask = 4278190080;

        private const string MSI_LIB = "msi";

        public const int MsiNullInteger = -2147483648;

        private MsiInterop()
        {
        }

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiAdvertiseProduct(string path, string script, string transforms, ushort langId);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiAdvertiseProductEx(string path, string script, string transforms, ushort langId, PlatformArchitecture platform, MsiAdvertismentOptions options);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiApplyPatch(string patchPackage, string installPackage, MsiInstallType installType, string commandLine);

        [DllImport("msi", CharSet = CharSet.None)]
        public static extern uint MsiCloseAllHandles();

        [DllImport("msi", CharSet = CharSet.None)]
        public static extern MsiError MsiCloseHandle(IntPtr handle);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiCollectUserInfo(string product);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiConfigureFeature(string product, string feature, MsiInstallState installState);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiConfigureProduct(string product, MsiInstallLevel level, MsiInstallState installState);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiConfigureProductEx(string product, MsiInstallLevel level, MsiInstallState installState, string commandLine);

        [DllImport("msi", CharSet = CharSet.None)]
        public static extern IntPtr MsiCreateRecord(uint count);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiCreateTransformSummaryInfo(IntPtr database, IntPtr databaseRef, string transformFile, MsiTransformError errorConditions, MsiValidationFlag validation);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiDatabaseApplyTransform(IntPtr database, string transformFile, MsiTransformError errorConditions);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiDatabaseCommit(IntPtr database);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiDatabaseExport(IntPtr database, string table, string folder, string fileName);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiDatabaseGenerateTransform(IntPtr database, IntPtr databaseRef, string transformFile, int reserved1, int reserved2);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiDatabaseGetPrimaryKeys(IntPtr database, string table, out IntPtr record);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiDatabaseImport(IntPtr database, string folder, string fileName);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiCondition MsiDatabaseIsTablePersistent(IntPtr database, string table);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiDatabaseMerge(IntPtr database, IntPtr merge, string table);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiDatabaseOpenView(IntPtr database, string query, out IntPtr view);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiDoAction(IntPtr database, string action);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiEnableLog(MsiInstallLogMode logMode, string logFile, MsiLogAttribute logAttributes);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiEnableUIPreview(IntPtr database, out IntPtr preview);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiEnumClients(string component, uint index, string product);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiEnumComponentCosts(IntPtr install, string component, uint index, MsiInstallState state, string drive, ref uint driveSize, out int cost, out int tempCost);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiEnumComponentQualifiers(string component, uint index, string qualifier, ref uint qualifierSize, string appData, ref int appDataSize);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiEnumComponents(uint index, string component);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiEnumFeatures(string product, uint index, StringBuilder feature, StringBuilder featureParent);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiEnumPatches(string product, uint index, string patch, string transform, ref uint transformSize);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiEnumProducts(uint index, string product);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiEnumRelatedProducts(string upgradeCode, uint reserved, uint index, StringBuilder product);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiCondition MsiEvaluateCondition(IntPtr install, string condition);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiFormatRecord(IntPtr install, IntPtr record, string result, ref uint resultSize);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern IntPtr MsiGetActiveDatabase(IntPtr install);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiInstallState MsiGetComponentPath(string product, string component, string path, ref uint pathSize);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiGetComponentState(IntPtr install, string component, out MsiInstallState state, out MsiInstallState action);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiDbState MsiGetDatabaseState(IntPtr database);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiGetFeatureCost(IntPtr install, string feature, MsiCostTree costTree, MsiInstallState state, out int cost);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiGetFeatureInfo(IntPtr productHandle, string feature, MsiInstallFeatureAttribute attributes, string title, ref uint titleSize, string help, ref uint helpSize);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiGetFeatureState(IntPtr install, string feature, out MsiInstallState state, out MsiInstallState action);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiGetFeatureUsage(string product, string feature, out uint useCount, out ushort dateUsed);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiGetFeatureValidStates(IntPtr install, string feature, out MsiFeatureInstallState state);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiGetFileVersion(string path, string version, ref uint versionSize, string language, ref uint languageSize);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern ushort MsiGetLanguage(IntPtr install);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern IntPtr MsiGetLastErrorRecord();

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern bool MsiGetMode(IntPtr install, MsiRunMode mode);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiGetPatchInfo(string patch, string attribute, string value, ref uint valueSize);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiGetProductCode(string component, string product);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiGetProductInfo(string product, string property, string value, ref uint valueSize);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiGetProductInfoFromScript(string scriptFile, string product, ref ushort langId, ref uint version, string name, ref uint nameSize, string package, ref uint packageSize);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiGetProductProperty(IntPtr productHandle, string property, string value, ref uint valueSize);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiGetProperty(IntPtr install, string name, string value, ref uint valueSize);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiGetShortcutTarget(string target, string product, string feature, string component);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiGetSourcePath(IntPtr install, string folder, string path, ref uint pathSize);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiGetSummaryInformation(IntPtr install, string path, uint updateCount, out IntPtr summaryInfo);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiGetTargetPath(IntPtr install, string folder, string path, ref uint pathSize);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiUserInfoState MsiGetUserInfo(string product, string user, ref uint userSize, string org, ref uint orgSize, string serial, ref uint serialSize);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiInstallMissingComponent(string product, string component, MsiInstallState state);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiInstallMissingFile(string product, string file);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiInstallProduct(string product, string commandLine);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiIsProductElevated(string product, out bool elevated);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiInstallState MsiLocateComponent(string component, string path, ref uint pathSize);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiOpenDatabase(string path, MsiDbPersistMode persist, out IntPtr handle);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiOpenPackage(string path, out IntPtr handle);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiOpenPackageEx(string path, MsiOpenPackageFlags options, out IntPtr handle);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiOpenProduct(string product, out IntPtr handle);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiPreviewBillboard(IntPtr preview, string name, string billboard);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiPreviewDialog(IntPtr preview, string dialog);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern int MsiProcessMessage(IntPtr install, MsiInstallMessage type, IntPtr record);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern uint MsiProvideAssembly(string assembly, string context, uint mode, MsiAssemblyInfo info, string path, ref int pathSize);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern uint MsiProvideComponent(string product, string feature, string component, uint mode, string path, ref int pathSize);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiProvideQualifiedComponent(string component, string qualifier, uint mode, string path, ref int pathSize);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiProvideQualifiedComponentEx(string component, string qualifier, uint mode, string product, uint unused1, uint unused2, string path, ref int pathSize);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiInstallState MsiQueryFeatureState(string product, string feature);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiInstallState MsiQueryProductState(string product);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiRecordClearData(IntPtr record);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern uint MsiRecordDataSize(IntPtr record, uint field);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern uint MsiRecordGetFieldCount(IntPtr record);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern int MsiRecordGetInteger(IntPtr record, uint field);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiRecordGetString(IntPtr record, uint field, string value, ref uint valueSize);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern bool MsiRecordIsNull(IntPtr record, uint field);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiRecordReadStream(IntPtr record, uint field, string buffer, ref uint bufferSize);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiRecordSetInteger(IntPtr record, uint field, int value);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiRecordSetStream(IntPtr record, uint field, string path);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiRecordSetString(IntPtr record, uint field, string value);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiReinstallFeature(string product, string feature, MsiReinstallMode mode);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiReinstallProduct(string product, MsiReinstallMode mode);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiSequence(IntPtr install, string table, int mode);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiSetComponentState(IntPtr install, string component, MsiInstallState state);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiInstallUIHandler MsiSetExternalUI(MsiInstallUIHandler handler, MsiInstallLogMode filter, IntPtr context);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiSetFeatureAttributes(IntPtr install, string feature, MsiInstallFeatureAttribute attributes);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiSetFeatureState(IntPtr install, string feature, MsiInstallState state);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiSetInstallLevel(IntPtr install, int level);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiInstallUILevel MsiSetInternalUI(MsiInstallUILevel level, ref IntPtr parentWindow);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiSetMode(IntPtr install, MsiRunMode mode, bool state);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiSetProperty(IntPtr install, string name, string value);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiSetTargetPath(IntPtr install, string folder, string path);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiSourceListAddSource(string product, string user, uint reserved, string source);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiSourceListClearAll(string product, string user, uint reserved);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiSourceListForceResolution(string product, string user, uint reserved);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiSummaryInfoGetProperty(IntPtr summaryInfo, uint id, out VariantType type, out int intValue, out FILETIME fileTime, string value, ref int valueSize);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiSummaryInfoGetPropertyCount(IntPtr summaryInfo, out int count);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiSummaryInfoPersist(IntPtr summaryInfo);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiSummaryInfoSetProperty(IntPtr summaryInfo, uint id, VariantType type, int intValue, FILETIME fileTime, string value);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiInstallState MsiUseFeature(string product, string feature);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiInstallState MsiUseFeatureEx(string product, string feature, MsiInstallMode mode, uint reserved);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiVerifyDiskSpace(IntPtr install);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiVerifyPackage(string path);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiViewClose(IntPtr view);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiViewExecute(IntPtr view, IntPtr record);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiViewFetch(IntPtr view, ref IntPtr record);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiViewGetColumnInfo(IntPtr view, MsiColInfoType type, out IntPtr record);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiDbError MsiViewGetError(IntPtr view, string columnNames, ref uint columnNamesSize);

        [DllImport("msi", CharSet = CharSet.Auto)]
        public static extern MsiError MsiViewModify(IntPtr view, MsiModify mode, IntPtr record);
    }
}
